import * as vscode from 'vscode';
import * as def from './DistBuildDefintions';
import { DistBuildDataManager } from './DataManager';
import * as cp from 'child_process';
import * as path from 'path';


export class DistBuildTaskProvider implements vscode.TaskProvider {
    static type = "distbuild";
    private _context: vscode.ExtensionContext
    constructor(context: vscode.ExtensionContext) {
        this._context = context;

    }
    provideTasks(token: vscode.CancellationToken): vscode.ProviderResult<vscode.Task[]> {
        console.log("on provide task");
        return getTasks();
    }
    resolveTask(_task: vscode.Task, token: vscode.CancellationToken): vscode.ProviderResult<vscode.Task> {
        const definition: def.DistBuildDefinition = <any>_task.definition;
        let envHosts: string[] = [];
        envHosts.push(`localhost/2`)
        let distBuildHosts = DistBuildDataManager.getInstance(this._context.extensionPath).getDistHosts();
        if (distBuildHosts !== undefined) {
            distBuildHosts.forEach(hostObj => {
                let host = hostObj.address
                if (host === '' || host === undefined) {
                    return
                }
                let port = hostObj.port ? hostObj.port : 3632;
                let jobs = hostObj.jobs ? hostObj.jobs : 4;
                envHosts.push(`${host}:${port}/${jobs}`)
            });
        }

        if (envHosts.length === 1) {
            vscode.window.showErrorMessage("请添加编译机!");
            return undefined;
        }

        let env = {
            PATH: "/usr/lib/distcc:${env:PATH}",
            DISTCC_HOSTS: envHosts.join(" "),
        }

        let options: vscode.ShellExecutionOptions = {
            env: env
        };
        let cmd = definition.command + " " + definition.args.join(" ");
        vscode.tasks.onDidStartTaskProcess(e => {
            if (e.execution.task.name.startsWith('distbuild:')) {
                let state = cp.spawn('/usr/bin/distccmon-text', ["1"]);
                state.stdout.on('data', data => {
                    let files: def.DistBuildStateFile[] = []
                    let addressMap = new Map<string, def.DistBuildStateFile[]>()
                    for (let line of ('' + data).split('\n')) {
                        if (line === '') {
                            continue
                        }
                        let fields = line.split(" ");
                        //console.log(fields.length);
                        let state = fields[2]
                        let file = fields[7]
                        let address = fields[fields.length - 1]

                        address = address.substring(0, address.indexOf('['))
                        if (!addressMap.has(address)) {
                            addressMap.set(address, [])
                        }

                        let fileState: def.DistBuildStateFile = {
                            filename: file,
                            state: state
                        }
                        //files.push(fileState)
                        addressMap.get(address)?.push(fileState)
                    }
                    if (addressMap.size > 0) {
                        for (let entry of addressMap.entries()) {
                            DistBuildDataManager.getInstance(this._context.extensionPath).updateDistBuildState(entry[0], entry[1])
                        }
                    }
                })
                state.stderr.on('data', data => {
                    //console.log("stderr" + data)
                })
                state.on('exit', code => {
                    //console.log("exit" + code)
                })
            }
        })
        vscode.tasks.onDidEndTaskProcess(e => {
            if (e.execution.task.name.startsWith('distbuild:')) {
                DistBuildDataManager.getInstance(this._context.extensionPath).cleanDistBuildState()
            }
        })
        let shell = new vscode.ShellExecution(cmd, options);
        return new vscode.Task(definition, _task.scope ?? vscode.TaskScope.Workspace, _task.name, _task.source, shell);
    }

}

async function getTasks(): Promise<vscode.Task[]> {
    /*
    */
    const result: vscode.Task[] = [];
    const kind: def.DistBuildDefinition = {
        type: DistBuildTaskProvider.type,
        command: "make",
        group: "build",
        args: ["-j", "4"]
    };
    let options: vscode.ShellExecutionOptions = {
        env: {
            PATH: "/usr/lib/distcc:${env:PATH}",
            DISTCC_HOSTS: "localhost"
        }
    };
    let cmd = kind.command + " " + kind.args.join();
    let shell = new vscode.ShellExecution(cmd, options);
    const task = new vscode.Task(kind, vscode.TaskScope.Workspace, "make", DistBuildTaskProvider.type, shell);
    result.push(task);
    return result;
}